package com.samsung.spen.sshare.networking.networkservice;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.acl.NotOwnerException;
import java.util.Map;

import com.samsung.spen.sshare.R;
import com.samsung.spen.sshare.main.sms.RequestSMSListFragment;
import com.samsung.spen.sshare.main.sms.SMSSender;
import com.samsung.spen.sshare.networking.connection.ConnectionListActivity;
import com.samsung.spen.sshare.networking.connection.NetworkReceivedFileConfirmDialog_Activity;
import com.samsung.spen.sshare.networking.sendreceivefile.SendReceiveActivity;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;

import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class SendReceiveService extends Service {

	public static final int RECEIVE = 10;

	// Miss Van
	private final int ONGOINGSERVICE_NOTI_ID = 100;
	private NotificationManager notificationManager;
	private static Context context;
	private boolean isStop;
	private ServerSocket mServerSocket = null;
	public static final String DISCONNECT = "NO";
	public static final String CONNECT = "YES";
	public static final String DATA = "FILE";
	public static final String INDEX = "INDEX";
	public static final String DATALIST = "LIST";

	public static final int REQUEST_SEND_SMS = 1;
	public static final int REQUEST_REPLY_SMS = 2;
	
	public static final String IP = "IP";
	public static final String PORT = "PORT";
	public static final String PHONE_NUM = "phoneNum";
	public static final String MSG_CONTENT = "content";

	private byte[] buf;
	private static final int mTCP_SERVER_PORT = 5678;
	private static final String TAG = "SENDRECEIVESERVICE";
	public static final String HEADER_KEY = "HEADER_KEY";
	public static final String BODY_KEY = "BODY_KEY";
	public static final String SERVICE = "SERVICE";
	public static String host;

	private final IBinder mBinder = new LocalBinder();

	public class LocalBinder extends Binder {
		public SendReceiveService getService() {
			return SendReceiveService.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub

		buf = new byte[4096];
		showNotification();

		return mBinder;
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		notificationManager.cancel(ONGOINGSERVICE_NOTI_ID);
		if (mServerSocket != null) {
			try {
				mServerSocket.close();
				mServerSocket = null;
				Log.i(TAG, "vao onDestroy() cua Service");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public void onRebind(Intent intent) {
		// TODO Auto-generated method stub
		super.onRebind(intent);
		Log.i(TAG, "vao onRebind()");
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(TAG, "vao onUnbind()");
		return super.onUnbind(intent);

	}

	class ReceiveThread extends Thread {
		Socket clientSock;

		public ReceiveThread(Socket socket) {
			// TODO Auto-generated constructor stub
			this.clientSock = socket;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			try {

				DataInputStream is = new DataInputStream(
						new BufferedInputStream(clientSock.getInputStream()));
				String receiveFromClient = is.readUTF();

				Log.i(TAG, receiveFromClient);

				String[] tokens = receiveFromClient.split("%");
				String index=receiveFromClient.split("%")[2];

				if (receiveFromClient.startsWith(CONNECT)) {
					Log.i(TAG, "YES");
					// Miss.Van task
					int port = is.readInt();
					Log.d(TAG, "SERVICE on PORT = " + port);
					Bundle data = new Bundle();
					data.putString("IP", clientSock.getInetAddress()
							.getHostAddress());
					data.putInt("PORT", port);

					Message msg = new Message();
					msg.what = ConnectionListActivity.MSG_ADD_ITEM;
					// msg.obj = CONNECT;
					msg.setData(data);

					RequestSMSListFragment.updateConnectionListHandler.sendMessage(msg);
//					ConnectionListActivity.uiHandler.sendMessage(msg);
				} else if (receiveFromClient.startsWith(DISCONNECT)) {
					Log.i(TAG, "NO");
					// Miss.Van task
					Bundle data = new Bundle();
					data.putString("IP", clientSock.getInetAddress()
							.getHostAddress());

					Message msg = new Message();
					msg.what = ConnectionListActivity.MSG_DELETE_ITEM;
					// msg.obj = DISCONNECT;
					msg.setData(data);
					RequestSMSListFragment.updateConnectionListHandler.sendMessage(msg);
//					ConnectionListActivity.uiHandler.sendMessage(msg);

				} else if (tokens[0].toUpperCase().equals(DATALIST)) {
					Log.i(TAG, "LIST");

					Intent i_dataList = new Intent(context,
							NetworkReceivedFileConfirmDialog_Activity.class);
					i_dataList.putExtra(DATALIST, receiveFromClient);
					i_dataList.putExtra(IP, clientSock.getInetAddress()
							.getHostAddress());
					i_dataList.putExtra(PORT, clientSock.getPort() + "");
					i_dataList.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					startActivity(i_dataList);
					
				} else if (tokens[0].toUpperCase().equals(INDEX)) {
					Log.i(TAG, "INDEX");

					Message msgSendReceive = SendReceiveActivity.mHandler
							.obtainMessage();
					msgSendReceive.what = RECEIVE;
					msgSendReceive.obj = receiveFromClient;
					SendReceiveActivity.mHandler.sendMessage(msgSendReceive);
				} else if (tokens[0].toUpperCase().equals(DATA)) {
					Log.i(TAG, "FILE " + tokens[1]);

					File folder = new File(
							Environment.getExternalStorageDirectory(), "SShare");
					if (!folder.exists()) {
						folder.mkdir();
					}

					File file = new File(
							Environment.getExternalStorageDirectory()
									+ "/SShare/" + tokens[1]);
					file.createNewFile();
					FileOutputStream fos = new FileOutputStream(file);
					int n = 0;
					long lengthOfFile = 0; // Update progress bar
					while ((n = is.read(buf)) != -1) {
						fos.write(buf, 0, n);
						fos.flush();
						lengthOfFile += n;
						Log.e("receive", "percent: "+lengthOfFile);
						SendReceiveActivity.filesRequest.get(Integer.parseInt(index)).percent=(int)lengthOfFile%100;
					}
					fos.close();
					is.close();
					Log.i(TAG, "da nhan xong");
				} else {
					Log.i(TAG, "NOTHING");
				}

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}

	// public void send(final String text,final String filePath) {
	//
	// new Thread() {
	// Socket socket = null;
	//
	// public void run() {
	//
	// try {
	// socket = new Socket();
	// Log.i(TAG, "vao truyen du lieu");
	// socket.connect(
	// new InetSocketAddress(host, mTCP_SERVER_PORT), 5000);
	// Log.i(TAG, "ket noi server xong");
	//
	// DataOutputStream dos=new DataOutputStream(new
	// BufferedOutputStream(socket.getOutputStream()));
	//
	// if(filePath!=null){
	// Log.i(TAG+"SEND",filePath);
	// String[] tokens=filePath.split("/");
	// String fileName=tokens[tokens.length-1];
	// dos.writeUTF(text+fileName);
	// dos.flush();
	//
	// File file=new File(filePath);
	// FileInputStream fis=new FileInputStream(file);
	//
	// int n=0;
	// long lengthOfFile=0;
	// while((n=fis.read(buf))!=-1){
	// dos.write(buf,0,n);
	// dos.flush();
	// lengthOfFile+=n;
	// }
	// fis.close();
	// dos.close();
	// Log.i(TAG, "da truyen xong");
	// }else{
	// dos.writeUTF(text);
	// dos.flush();
	// }
	//
	// } catch (UnknownHostException e) {
	// // TODO: handle exception
	// e.printStackTrace();
	// Log.i(TAG, "UnknownHostException");
	// }catch (FileNotFoundException e) {
	// // TODO: handle exception
	// e.printStackTrace();
	// Log.i(TAG, "File not found");
	// }
	// catch (IOException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// Log.i(TAG, "IO exception");
	// } finally {
	// if (socket != null) {
	// if (socket.isConnected()) {
	// try {
	// socket.close();
	// Log.i(TAG, "Socket da dong");
	// socket = null;
	// } catch (IOException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }
	//
	// }
	// }
	// };
	// }.start();
	// }

	// public void listening() {
	// Log.i(TAG, "cho ket noi den");
	//
	// if (serverSock != null) {
	// new Thread() {
	//
	// public void run() {
	// Socket clientSock = null;
	// try {
	// while (true) {
	// clientSock = serverSock.accept();
	// new ReceiveThread(clientSock).start();
	// }
	// } catch (IOException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// } finally {
	// try {
	// clientSock.close();
	// } catch (IOException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }
	//
	// };
	// }.start();
	// } else {
	// Log.i(TAG, "serverSock bi null");
	// }
	// }

	/*
	 * Start a server
	 * 
	 * @param request: (static attribute of ServerSocketService.class) request
	 * after an instance of ServerSocket is created. It can accept arg
	 * REQUEST_REPLY_SMS to respond a SMS request or REQUEST_SEND_SMS to create
	 * a SMS request.
	 * 
	 * @param addr: if 'request' = REQUEST_SEND_SMS, 'addr' must have an item
	 * (key,value)=("PHONE","phone-number");if 'request' = REQUEST_REPLY_SMS,
	 * 'addr' must have two items (key, value)=("IP","friend'sIP") and (key,
	 * value)=("PORT","friend'sPORT")
	 */
	public void startServer(final int request, final Map<String, String> addr) {
		this.isStop = false;
		context = this;

		if (mServerSocket != null) {
			sendRequest(request, addr);
			Log.i(TAG, "mServerSocket != null");
			Log.d(TAG, "Server starts on port: " + mServerSocket.getLocalPort());
			return;
		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					// TODO Create server socket with a random port
					mServerSocket = new ServerSocket(0);
					Log.d(TAG, "Server's IP: "
							+ mServerSocket.getInetAddress().getHostAddress());
					Log.d(TAG,
							"Server starts on port: "
									+ mServerSocket.getLocalPort());

					sendRequest(request, addr);

					while (!isStop) {

						Socket clientSocket = mServerSocket.accept();

						String msg = "--Report--"
								+ clientSocket.getInetAddress()
										.getHostAddress() + " is connected";

						Message uiMsg = new Message();
						uiMsg.obj = msg;

						// networkHandler.sendMessage(uiMsg);

						// new NetworkThread(clientSocket).start();
						new ReceiveThread(clientSocket).start();
					}

				} catch (IOException e) {
					Log.e("FileShare", "Can not open server socket");
					e.printStackTrace();
				}
			}
		}).start();

	}

	private void sendRequest(final int request, final Map<String, String> addr) {
		switch (request) {
		case REQUEST_SEND_SMS:
			 String myIP = Utils.getIPAddress(Utils.WLAN0);
			 int myPort = mServerSocket.getLocalPort();
			 String peerPhoneNum = addr.get(PHONE_NUM);
			 String userMsg = addr.get(MSG_CONTENT);
			
			 SMSSender smsSender = new SMSSender();
			 String content = smsSender.buildSshareSMS(myIP, myPort, userMsg);
			 smsSender.sendSMS(context, peerPhoneNum, content);
	
			break;
		case REQUEST_REPLY_SMS:
			(new SendingDataTask()).execute(addr.get(IP), addr.get(PORT),
					CONNECT, "" + mServerSocket.getLocalPort());
			break;
		default:
			break;
		}

	}

	private void showNotification() {
		/* NotificationManager */notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

		Intent intent = new Intent(this, ConnectionListActivity.class);
		PendingIntent pendingInten = PendingIntent.getActivity(this, 0, intent,
				Intent.FLAG_ACTIVITY_SINGLE_TOP);

		Notification noti = new Notification(R.drawable.ic_launcher,
				"FileSharing", System.currentTimeMillis());
		noti.setLatestEventInfo(this, "FileShare", "Ongoing", pendingInten);
		noti.flags |= /* Notification.FLAG_ONGOING_EVENT | */Notification.FLAG_FOREGROUND_SERVICE;

		notificationManager.notify(ONGOINGSERVICE_NOTI_ID, noti);

	}

}
